﻿// Decompiled with JetBrains decompiler
// Type: DnProcessSimulateCommands.ToolPositioningInternal.CApTPIContourManipulator
// Assembly: DnProcessSimulateCommands, Version=2402.0.0.890, Culture=neutral, PublicKeyToken=null
// MVID: A885D881-AEDF-447E-852A-6F13102E089C
// Assembly location: C:\Program Files\Tecnomatix_2402\eMPower\DotNetCommands\DnProcessSimulateCommands.dll

using EngineeringInternalExtension;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using Tecnomatix.Engineering;


namespace DnProcessSimulateCommands.ToolPositioningInternal;

internal class CApTPIContourManipulator
{
  private TxContour _contour;
  private List<TxContour> _contours = new List<TxContour>();
  private Random _randomAngle = new Random();
  private Random _randomAxis = new Random();
  public const double _maxDistBetweenFirstAndLastPoints = 0.001;
  public Action GenerationFinished;
  public Action<TxContour> NewContour;

  public bool IsManipulationInProgress { get; set; }

  public TxContour Contour
  {
    get => this._contour;
    set
    {
      if (value == this._contour)
        return;
      this._contour = value;
      this._contours.Clear();
    }
  }

  public List<TxContour> Contours => this._contours;

  private void SetRotationVectorAxisAngle(TxVector vector, AxisType axis, double angleDegrees)
  {
    double num = angleDegrees * (Math.PI / 180.0);
    switch (axis)
    {
      case AxisType.RX:
        vector.X = num;
        break;
      case AxisType.RY:
        vector.Y = num;
        break;
      case AxisType.RZ:
        vector.Z = num;
        break;
    }
  }

  public void CreateContours(int number)
  {
    this.IsManipulationInProgress = true;
    TxVector txVector = new TxVector();
    int num1 = number / 3;
    int num2 = number % 3;
    TxVector vector = new TxVector();
    for (int index = 0; index < number && this.IsManipulationInProgress; ++index)
    {
      vector.X = 0.0;
      vector.Y = 0.0;
      vector.Z = 0.0;
      int num3 = this._randomAxis.Next(0, 7);
      Func<int> func = (Func<int>) (() => this._randomAngle.Next(0, 360));
      int angleDegrees1 = func();
      switch (num3)
      {
        case 0:
          this.SetRotationVectorAxisAngle(vector, AxisType.RX, (double) angleDegrees1);
          break;
        case 1:
          this.SetRotationVectorAxisAngle(vector, AxisType.RY, (double) angleDegrees1);
          break;
        case 2:
          this.SetRotationVectorAxisAngle(vector, AxisType.RZ, (double) angleDegrees1);
          break;
        case 3:
          this.SetRotationVectorAxisAngle(vector, AxisType.RX, (double) angleDegrees1);
          int angleDegrees2 = func();
          this.SetRotationVectorAxisAngle(vector, AxisType.RY, (double) angleDegrees2);
          break;
        case 4:
          this.SetRotationVectorAxisAngle(vector, AxisType.RX, (double) angleDegrees1);
          int angleDegrees3 = func();
          this.SetRotationVectorAxisAngle(vector, AxisType.RZ, (double) angleDegrees3);
          break;
        case 5:
          this.SetRotationVectorAxisAngle(vector, AxisType.RY, (double) angleDegrees1);
          int angleDegrees4 = func();
          this.SetRotationVectorAxisAngle(vector, AxisType.RZ, (double) angleDegrees4);
          break;
        case 6:
          this.SetRotationVectorAxisAngle(vector, AxisType.RX, (double) angleDegrees1);
          int angleDegrees5 = func();
          this.SetRotationVectorAxisAngle(vector, AxisType.RY, (double) angleDegrees5);
          int angleDegrees6 = func();
          this.SetRotationVectorAxisAngle(vector, AxisType.RZ, (double) angleDegrees6);
          break;
      }
      TxContour txContour = new TxContour(this._contour);
      txContour.Center = new TxTransformation(txVector, vector, (TxTransformation.TxRotationType) 1);
      this._contours.Add(txContour);
      Action<TxContour> newContour = this.NewContour;
      if (newContour != null)
        newContour(txContour);
    }
    this.IsManipulationInProgress = false;
  }

  public static List<TxVector> ScaleContour(List<TxVector> contourPoints)
  {
    double a = double.MinValue;
    List<TxVector> txVectorList = new List<TxVector>();
    foreach (TxVector contourPoint in contourPoints)
    {
      if (Math.Abs(contourPoint.X) > a)
        a = Math.Abs(contourPoint.X);
      if (Math.Abs(contourPoint.Y) > a)
        a = Math.Abs(contourPoint.Y);
      if (Math.Abs(contourPoint.Z) > a)
        a = Math.Abs(contourPoint.Z);
      txVectorList.Add(contourPoint);
    }
    if (a > 1.0)
    {
      double num = Math.Ceiling(a);
      for (int index = 0; index < txVectorList.Count; ++index)
      {
        TxVector txVector = txVectorList[index];
        txVector.X /= num;
        txVector.Y /= num;
        txVector.Z /= num;
      }
    }
    return txVectorList;
  }

  private static bool IsContourClosed(List<TxVector> points)
  {
    return points.Count > 1 && CApTPIContourManipulator.GetDistanceBetweenPoints(points[0], points[points.Count - 1]) <= 0.001;
  }

  private static List<TxVector> CloseContour(List<TxVector> points)
  {
    if (points.Count > 1 && CApTPIContourManipulator.GetDistanceBetweenPoints(points[0], points[points.Count - 1]) > 0.001)
      points.Add(points[0]);
    return points;
  }

  public static List<TxVector> MakeCloseContour(List<TxVector> points)
  {
    if (!CApTPIContourManipulator.IsContourClosed(points))
      points = CApTPIContourManipulator.CloseContour(points);
    return points;
  }

  public static double GetDistanceBetweenPoints(TxVector point1, TxVector point2)
  {
    double distanceBetweenPoints = 0.0;
    if (TxVector.op_Inequality(point1, (TxVector) null) && TxVector.op_Inequality(point2, (TxVector) null))
    {
      TxVector txVector = TxVector.Subtract(point1, point2);
      distanceBetweenPoints = Math.Sqrt(TxVector.DotProduct(txVector, txVector));
    }
    return distanceBetweenPoints;
  }

  public static string ConvertContourPointsToString(List<TxVector> points, int maxPointsNum)
  {
    CultureInfo invariantCulture = CultureInfo.InvariantCulture;
    string format = "0.000000000000";
    string str1 = "0.0,0.0,0.0";
    StringBuilder stringBuilder1 = new StringBuilder();
    foreach (TxVector point in points)
    {
      if (stringBuilder1.Length != 0)
        stringBuilder1.Append(",");
      StringBuilder stringBuilder2 = stringBuilder1;
      string[] strArray = new string[5];
      double num = point.X;
      strArray[0] = num.ToString(format, (IFormatProvider) invariantCulture);
      strArray[1] = ",";
      num = point.Y;
      strArray[2] = num.ToString(format, (IFormatProvider) invariantCulture);
      strArray[3] = ",";
      num = point.Z;
      strArray[4] = num.ToString(format, (IFormatProvider) invariantCulture);
      string str2 = string.Concat(strArray);
      stringBuilder2.Append(str2);
    }
    if (points.Count < maxPointsNum)
    {
      int count = maxPointsNum - points.Count;
      stringBuilder1.Append(string.Concat(Enumerable.Repeat<string>("," + str1, count)));
    }
    return stringBuilder1.ToString();
  }

  internal static List<TxVector> DecimatePolyline(
    List<TxVector> polyline,
    int maxNumberOfPoints,
    out double epsilon)
  {
    List<TxVector> txVectorList1 = new List<TxVector>();
    epsilon = 0.0;
    if (polyline.Count > maxNumberOfPoints)
    {
      TxContour txContour = new TxContour(polyline, true);
      epsilon = CApTPIContourManipulator.GetDistanceBetweenPoints(txContour.FarthestPointFromCenter, txContour.Center.Translation);
      if (epsilon > 0.0)
      {
        double epsilon1 = epsilon;
        double num = epsilon;
        List<TxVector> txVectorList2 = new List<TxVector>();
        while (txVectorList2.Count != maxNumberOfPoints && num > 1E-08)
        {
          num /= 2.0;
          if (txVectorList2.Count > maxNumberOfPoints)
            epsilon1 += num;
          else if (txVectorList2.Count < maxNumberOfPoints)
            epsilon1 -= num;
          txVectorList2 = CApTPIContourManipulator.DecimatePolyline(polyline, epsilon1);
          if (txVectorList2.Count <= maxNumberOfPoints)
          {
            txVectorList1 = txVectorList2;
            epsilon = epsilon1;
          }
        }
      }
    }
    return txVectorList1;
  }

  internal static List<TxVector> DecimatePolyline(List<TxVector> polyline, double epsilon)
  {
    List<TxVector> txVectorList1 = new List<TxVector>();
    if (polyline.Count > 1)
    {
      double num1 = 0.0;
      int index1 = 0;
      bool flag = true;
      TxLineData txLineData = new TxLineData(polyline[0], polyline[polyline.Count - 1]);
      if (txLineData.Length > 0.0)
      {
        flag = false;
        for (int index2 = 1; index2 < polyline.Count - 1; ++index2)
        {
          double num2;
          TxParameterizedPoint parameterizedPoint;
          txLineData.GetPointProjection(polyline[index2], ref num2, ref parameterizedPoint);
          if (num2 > num1)
          {
            index1 = index2;
            num1 = num2;
          }
        }
      }
      if (num1 > epsilon | flag)
      {
        if (flag)
        {
          txVectorList1.Add(polyline[0]);
          List<TxVector> collection = CApTPIContourManipulator.DecimatePolyline(polyline.GetRange(1, polyline.Count - 1), epsilon);
          txVectorList1.AddRange((IEnumerable<TxVector>) collection);
        }
        else
        {
          List<TxVector> txVectorList2 = CApTPIContourManipulator.DecimatePolyline(polyline.GetRange(0, index1 + 1), epsilon);
          List<TxVector> collection = CApTPIContourManipulator.DecimatePolyline(polyline.GetRange(index1, polyline.Count - index1), epsilon);
          if (txVectorList2.Count > 0)
            txVectorList1.AddRange((IEnumerable<TxVector>) txVectorList2.GetRange(0, txVectorList2.Count - 1));
          txVectorList1.AddRange((IEnumerable<TxVector>) collection);
        }
      }
      else
      {
        txVectorList1.Add(polyline[0]);
        txVectorList1.Add(polyline[polyline.Count - 1]);
      }
    }
    else if (polyline.Count == 1)
      txVectorList1.Add(polyline[0]);
    return txVectorList1;
  }

  public static List<TxVector> SaturatePolyline(
    List<TxVector> polyline,
    double minPointsDist,
    int maxNumPoints)
  {
    LinkedList<TxVector> source = new LinkedList<TxVector>((IEnumerable<TxVector>) polyline);
    if (source.Count > 1 && maxNumPoints > source.Count)
    {
      int num = maxNumPoints - source.Count;
      LinkedListNode<TxVector> node = source.First;
      LinkedListNode<TxVector> linkedListNode = node.Next;
      bool flag = false;
      while (num > 0)
      {
        if (node.Previous == null)
          flag = false;
        if (CApTPIContourManipulator.GetDistanceBetweenPoints(node.Value, linkedListNode.Value) >= 2.0 * minPointsDist)
        {
          TxVector txVector = TxVector.op_Division(TxVector.op_Addition(node.Value, linkedListNode.Value), 2.0);
          node = source.AddAfter(node, txVector);
          flag = true;
          --num;
        }
        if (linkedListNode.Next == null)
        {
          if (flag)
            flag = false;
          else
            break;
        }
        node = node.Next ?? node.List.First;
        linkedListNode = node.Next ?? node.List.First;
      }
    }
    return source.ToList<TxVector>();
  }

  public static TxVector FindClosestContourPointFromContourCenter(
    TxVector contourCenter,
    List<TxVector> points,
    out double closestDist)
  {
    TxVector fromContourCenter = (TxVector) null;
    closestDist = 0.0;
    if (points.Count > 0)
    {
      fromContourCenter = points[0];
      closestDist = double.MaxValue;
      for (int index = 1; index < points.Count; ++index)
      {
        double distanceBetweenPoints = CApTPIContourManipulator.GetDistanceBetweenPoints(points[index], contourCenter);
        if (distanceBetweenPoints < closestDist)
        {
          closestDist = distanceBetweenPoints;
          fromContourCenter = points[index];
        }
      }
    }
    return fromContourCenter;
  }

  public static TxVector FindFarthestContourPointFromContourCenter(
    TxVector contourCenter,
    List<TxVector> points,
    out double farthestDist)
  {
    TxVector fromContourCenter = (TxVector) null;
    farthestDist = 0.0;
    if (points.Count > 0)
    {
      fromContourCenter = points[0];
      farthestDist = double.MinValue;
      for (int index = 1; index < points.Count; ++index)
      {
        double distanceBetweenPoints = CApTPIContourManipulator.GetDistanceBetweenPoints(points[index], contourCenter);
        if (distanceBetweenPoints > farthestDist)
        {
          farthestDist = distanceBetweenPoints;
          fromContourCenter = points[index];
        }
      }
    }
    return fromContourCenter;
  }
}
